using System;
using System.Runtime.Serialization;
using OhioState.AssetManaged;
using OhioState.Math;

namespace OhioState.Graphics.Proxy
{

    [Serializable()]
    public class SlicePlaneProxy : SharedAsset, IDrawable
    {

        private float _sliceThickness = 0.005f;
        public float SliceThickness
        {
            get { return _sliceThickness; }
            set
            {
                _sliceThickness = value;
                FireUpdateChangedEvent(this);
            }
        }
        private SliceDirection.SliceDirMode _sliceMode;
        public SliceDirection.SliceDirMode SlicingMode
        {
            get { return _sliceMode; }
            set
            {
                _sliceMode = value;
                FireUpdateChangedEvent(this);
            }
        }
        private Vector3 _sliceDirection = new Vector3(1.0f, 0.0f, 1.0f);
        public Vector3 SliceDirection
        {
            get { return _sliceDirection; }
            set
            {
                _sliceDirection = value;
                FireUpdateChangedEvent(this);
            }
        }
        private Matrix4 _worldToROI = new Matrix4();
        public Matrix4 WorlToROIMatrix
        {
            get { return _worldToROI; }
            set
            {
                _worldToROI = value;
                FireUpdateChangedEvent(this);
            }

        }
        private Matrix4 _roiToTexture = new Matrix4();
        public Matrix4 ROIToTextureMatrix
        {
            get { return _roiToTexture; }
            set
            {
                _roiToTexture = value;
                FireUpdateChangedEvent(this);
            }
        }
        private IShape _iShape;
        private SharedBox sBox;
        private Plane _plane;
        //private ShapeType _shapeType;
        public SlicePlaneProxy(Plane plane, SharedBox sb)
            : base("SlicePlane")
        {
            sBox = sb;
            _iShape = sb;
            _plane = plane;
            //_shapeType = _ShapeType.Box;
            _material = MaterialProxy.White;
           
        }
              
        #region IDrawable interface
        public IBoundingVolume BoundingVolume
        {
            get { return ((SharedBox)_iShape).BBox; }
        }

        private OSUColor _color = new OSUColor(OSUColor.White);
        public OSUColor Color
        {
            get { return new OSUColor(_color); }
            set
            {
                _color = new OSUColor(value);
                FireUpdateChangedEvent(this);
            }
        }
        public void Update(IRenderPanel panel)
        {
        }
        private MaterialProxy _material;
        public IMaterial Material
        {
            get { return _material; }
            set
            {
                //
                // For fields that contain shared objects, follow this sequence:
                //   1. rewire the notification for the shared object
                //        this property points to.
                //   2. set the property.
                //   3. perform any internal updates.
                //   4. Implicit in step 3 would be changing this 
                //         object and hence notifying it's subscribers.
                //
                IAssetManagedHandler changedEvent = new IAssetManagedHandler(SPlane_ChangedEvent);
                MaterialProxy mat = value as MaterialProxy;
                if (mat != null)
                {
                    this.SetPropertyEventHandling(_material, mat, changedEvent);
                    _material = mat;
                    SPlane_ChangedEvent(mat);
                }
            }
        }
        public void Render(IRenderPanel panel)
        {
        }
        #endregion IDrawable interface

        private void SPlane_ChangedEvent(IAssetManaged obj)
        {
            FireUpdateChangedEvent(this);
        }
        /// <summary>
        /// Overrides shared object ToString method
        /// </summary>
        /// <returns>A string representing parent shared object name</returns>
        public override String ToString()
        {
            return base.Name;
        }


        # region Public Properties

        public Plane Plane
        {
            get { return _plane; }
            set
            {
                IAssetManagedHandler changedEvent = new IAssetManagedHandler(Plane_ChangedEvent);
                this.SetPropertyEventHandling(_plane, value, changedEvent);
                _plane = value;
                Plane_ChangedEvent(_plane);
            }
        }

        public IShape IShape
        {
            get { return sBox; }
            set
            {
                IAssetManagedHandler changedEvent = new IAssetManagedHandler(Shape_ChangedEvent);
                this.SetPropertyEventHandling(sBox, value, changedEvent);
                if( value is SharedBox)
                    sBox = (SharedBox)value;
                Shape_ChangedEvent(sBox);
            }
        }
        
        //public ShapeType ShapeType
        //{
        //    get { return ShapeType; }
        //    set 
        //    {
        //        ShapeType = value;
        //        FireUpdateChangedEvent(this);
        //    }
        //}

        #endregion
        private void SlicePlane_ChangedEvent(IAssetManaged obj)
        {
            FireUpdateChangedEvent(this);
        }

        protected void Plane_ChangedEvent(IAssetManaged obj)
        {
            FireUpdateChangedEvent(this);
        }

        protected void Shape_ChangedEvent(IAssetManaged obj)
        {
            FireUpdateChangedEvent(this);
        }

        public override void ReaquireAssets()
        {
            //
            // Use the Properties to ensure the old event handlers are removed and new
            //    ones are added. Particularly if we are setting an item to itself.
            //
            IAssetManaged item = AssetManager.Instance.Find(_plane.GetType(), _plane.Name);
            if (item != _plane)
            {
                this.Plane = item as Plane;
            }
            item = AssetManager.Instance.Find(_material.GetType(), _material.Name);
            if (item != _material)
            {
                this.Material = item as IMaterial;
            }
            item = AssetManager.Instance.Find(sBox.GetType(), sBox.Name);
            if (item != _iShape)
            {
                this.sBox = item as SharedBox;
            }
        }
        [OnDeserialized]
        private void OnDeserialized(StreamingContext context)
        {
            IAssetManagedHandler changedEvent = new IAssetManagedHandler(SlicePlane_ChangedEvent);
            _plane.AddChangedEventHandler(changedEvent);
            _material.AddChangedEventHandler(changedEvent);
            IAssetManaged obj = this.sBox as IAssetManaged;
            if (obj != null)
            {
                obj.AddChangedEventHandler(changedEvent);
            }
        }
    }

}
